/**
 * Input.js
 **/

define(function() {
    var Input = function() {
            
        this.mouseEventsSet = false;
        this.touchEventsSet = false;
        this.keyboardEventsSet = false;

        this.keyboard = {
            up : false,
            right : false,
            down : false,
            left : false,
            space : false,
            keypressed : false
        };

        this.evt = {
            // Positions
            x : null,
            y : null,
            prevX : null,
            prevY : null,

            // Simple states
            up : true,          // release touch or click
            down : false,       // touch or mouse down on canvas
            click : false,      // Single click/tap per frame

            // Complex states
            drag : false,       // Drag mouse or finger
            zoomin : false,     // Zooming in
            zoomout : false,    // Zooming out

            // Properties
            dzoom : 0,          // Distance between 2 fingers doing zoom
            touches : [],       // Touches currently on screen
        };

        this._isZooming = false;

        this.init = function(options) {
            options = options || {};

            this.target = options.target || document;
            this.controller = options.controller || null;
        }

        this.listen = function() {

            var that = this;

            this.target.addEventListener('stop', function(evt) {
                that.release();
            }, false);

            if(isMobileDevice() === false && isTabletDevice() === false) {
                this.listenMouse();
            } else {
                this.listenTouch();
            }

            this.listenKeyboard();

            this.zoom();

            this.evt.click = false;
        }

        this.listenMouse = function() {

            if (!this.mouseEventsSet)
                this.setMouseEvents();

        };

        this.listenTouch = function() {

            if (!this.touchEventsSet)
                this.setTouchEvents();

        };

        this.listenKeyboard = function() {

            if (!this.keyboardEventsSet)
                this.setKeyboardEvents();

        };

        this.setMouseEvents = function() {

            var that = this;

            that.evt.click = false;
            
            this.target.addEventListener('mousemove', function(evt) {
                that.updateMouse(evt);
            }, false);
                    
            this.target.addEventListener('mousedown', function(evt) {
                that.updateMouse(evt);
                that.evt.down = true;
                that.evt.up = false;
                that.evt.click = true;
            }, false);

            this.target.addEventListener('mouseup', function(evt) {
                that.updateMouse(evt);
                that.release();
            }, false);

            this.target.addEventListener('mousewheel', function(evt){
                that.evt.zoomin = evt.wheelDelta/120 < 0;
                that.evt.zoomout = evt.wheelDelta/120 > 0;
            }, false);

            this.target.addEventListener('contextmenu', function(evt) {
                    evt.preventDefault();
            }, false);

            this.mouseEventsSet = true;

        };

        this.setTouchEvents = function() {

            var that = this;

            that.evt.release = false;

            this.target.addEventListener('touchmove', function(evt){
                event.preventDefault();
                that.updateTouch(evt);
            }, false);


            this.target.addEventListener('touchstart', function(evt){
                that.updateTouch(evt);
                that.evt.down = true;
                that.evt.up = false;
                that.evt.click = true;
                that.evt.drag = false;
            }, false);

            this.target.addEventListener('touchend', function(evt){
                that.updateTouch(evt);
                that.release();
            }, false);

            this.touchEventsSet = true;
        }

        this.updateMouse = function(evt) {
            
            this.evt.prevX = this.evt.x;
            this.evt.prevY = this.evt.y;

            this.evt.x = parseInt(evt.clientX) - ( this.target.offsetLeft || 0 );
            this.evt.y = parseInt(evt.clientY) - ( this.target.offsetTop || 0 );
        };

        this.updateTouch = function(evt) {
                
            this.evt.touches = evt.touches;

            if(typeof this.evt.touches !== "undefined" && this.evt.touches.length === 1 && this._isZooming === false) {
                this.evt.prevX = this.evt.x;
                this.evt.prevY = this.evt.y;

                this.evt.x = parseInt(evt.touches[0].clientX) - ( this.target.offsetLeft || 0 );
                this.evt.y = parseInt(evt.touches[0].clientY) - ( this.target.offsetTop || 0 );
            }
        };

        this.setKeyboardEvents = function() {

            var that = this;

            document.addEventListener('keydown', function(evt) {

                that.keyboard.up    = evt.keyCode == 38 || evt.keyCode == 90 || evt.keyCode == 87 ? 1 : that.keyboard.up;
                that.keyboard.right = evt.keyCode == 39 || evt.keyCode == 68 ? 1 : that.keyboard.right;
                that.keyboard.down  = evt.keyCode == 40 || evt.keyCode == 83 ? 1 : that.keyboard.down;
                that.keyboard.left  = evt.keyCode == 37 || evt.keyCode == 81 || evt.keyCode == 65 ? 1 : that.keyboard.left;
                that.keyboard.space = evt.keyCode == 32 ? 1 : that.keyboard.space;

            }, false);

            document.addEventListener('keyup', function(evt) {

                that.keyboard.keypressed = true;

                that.keyboard.up    = evt.keyCode == 38 || evt.keyCode == 90 || evt.keyCode == 87 ? 0 : that.keyboard.up;
                that.keyboard.right = evt.keyCode == 39 || evt.keyCode == 68 ? 0 : that.keyboard.right;
                that.keyboard.down  = evt.keyCode == 40 || evt.keyCode == 83 ? 0 : that.keyboard.down;
                that.keyboard.left  = evt.keyCode == 37 || evt.keyCode == 81 || evt.keyCode == 65  ? 0 : that.keyboard.left;
                that.keyboard.space = evt.keyCode == 32 ? 0 : that.keyboard.space;

            }, false);

            this.keyboardEventsSet = true;

        };

        this.drag = function(target) {

            this.evt.drag = true;

            return {
                x : this.evt.x - target.transform.position.x,
                y : this.evt.y - target.transform.position.y
            };
        }

        this.zoom = function() {
            if(typeof this.evt.touches !== "undefined" && this.evt.touches.length === 2) {

                this._isZooming = true;

                var d = distance(
                    {x:this.evt.touches[0].clientX,y:this.evt.touches[0].clientY},
                    {x:this.evt.touches[1].clientX,y:this.evt.touches[1].clientY}
                );

                this.evt.zoomin = this.evt.dzoom !== 0 && d < this.evt.dzoom - 10;
                this.evt.zoomout = this.evt.dzoom !== 0 && d > this.evt.dzoom + 10;
                this.evt.dzoom = d;
            } else {
                this.evt.dzoom = 0;
                this.evt.zoomin = false;
                this.evt.zoomout = false;

                if(typeof this.evt.touches === "undefined" || this.evt.touches.length === 0) {
                    this._isZooming = false;
                }
            }
        }

        this.release = function() {
            this.evt.up = true;
            this.evt.down = false;
            this.evt.click = false;
            this.evt.drag = false;
        }

        this.trigger = function(name) {
            var event; // The custom event that will be created

            if (document.createEvent) {
                event = document.createEvent("HTMLEvents");
                event.initEvent(name, true, true);
            } else {
                event = document.createEventObject();
                event.eventType = name;
            }

            event.eventName = name;

            if (document.createEvent) {
                this.target.dispatchEvent(event);
            } else {
                this.target.fireEvent("on" + event.eventType, event);
            }
        }
    }

    return Input;
});